const config = require("./config");
const _knex = require("knex");
const _bookshelf = require("bookshelf");
const _ = require("lodash");
const compareVersions = require("compare-versions");
const paranoia = require("bookshelf-paranoia");
const cache = require("./lib/bookshelf/cache");
const pagination = require("./lib/bookshelf/pagination");
const visibility = require("./lib/bookshelf/visibility");

const getBookshelf = connection => {
  const knex = _knex(connection);
  const bookshelf = _bookshelf(knex);

  bookshelf.plugin(visibility);
  bookshelf.plugin(pagination);
  bookshelf.plugin(paranoia);
  bookshelf.plugin(cache);

  return bookshelf;
};

const bookshelf = getBookshelf({
  client: "mysql",
  connection: config.mysql
});

const Models = {
  auth: bookshelf.Model.extend({
    tableName: "baas2.auth",
    hasTimestamps: true,
    softDelete: true,
    class_table: function() {
      return this.hasMany(Models.class_table, "auth_id");
    }
  }),
  _auth: bookshelf.Model.extend({
    tableName: "baas2.auth",
    hasTimestamps: true,
    softDelete: true
  }),
  baas: bookshelf.Model.extend({
    tableName: "baas2.baas",
    hasTimestamps: true,
    softDelete: true,
    log_count: function() {
      return this.hasOne(Models.log_count, "baas_id");
    },
    charges: function() {
      return this.belongsTo(Models.charges, "charges_id");
    }
  }),
  class: bookshelf.Model.extend({
    tableName: "baas2.class",
    hasTimestamps: true,
    softDelete: true,
    baas: function() {
      return this.belongsTo(Models.baas, "baas_id");
    }
  }),
  class_auth: bookshelf.Model.extend({
    tableName: "baas2.class_auth",
    hasTimestamps: true,
    softDelete: true,
    class: function() {
      return this.belongsTo(Models.class, "class_id");
    },
    auth: function() {
      return this.belongsTo(Models.auth, "auth_id");
    }
  }),
  class_table: bookshelf.Model.extend({
    tableName: "baas2.class_table",
    hasTimestamps: true,
    softDelete: true,
    class: function() {
      return this.belongsTo(Models.class, "class_id");
    },
    auth: function() {
      return this.belongsTo(Models._auth, "auth_id");
    }
  }),
  class_field: bookshelf.Model.extend({
    tableName: "baas2.class_field",
    hasTimestamps: true,
    softDelete: true,
    class: function() {
      return this.belongsTo(Models.class, "class_id");
    }
  }),
  schedule: bookshelf.Model.extend({
    tableName: "baas2.class_schedule",
    hasTimestamps: true,
    softDelete: true,
    function: function() {
      return this.belongsTo(Models.function, "function_id");
    },
    class_auth: function() {
      return this.belongsTo(Models.class_auth, "class_id", "class_id");
    },
    class: function() {
      return this.belongsTo(Models.class, "class_id");
    }
  }),
  file: bookshelf.Model.extend({
    tableName: "baas2.file",
    hasTimestamps: true,
    softDelete: true
  }),
  relation: bookshelf.Model.extend({
    tableName: "baas2.relation",
    hasTimestamps: true,
    softDelete: true
  }),
  function: bookshelf.Model.extend({
    tableName: "baas2.class_function",
    hasTimestamps: true,
    softDelete: true,
    class: function() {
      return this.belongsTo(Models.class, "class_id");
    }
  }),
  hook: bookshelf.Model.extend({
    tableName: "baas2.class_hook",
    hasTimestamps: true,
    softDelete: true,
    class: function() {
      return this.belongsTo(Models.class, "class_id");
    }
  }),
  global: bookshelf.Model.extend({
    tableName: "baas2.global",
    hasTimestamps: true,
    softDelete: true,
    class: function() {
      return this.belongsTo(Models.class, "class_id");
    }
  }),
  table: bookshelf.Model.extend({
    tableName: "baas2.table",
    hasTimestamps: true,
    softDelete: true
  }),
  user: bookshelf.Model.extend({
    tableName: "baas2_dashboard.user",
    hasTimestamps: true,
    softDelete: true,
    hidden: ["password_org"],
    user_info: function() {
      return this.hasOne(Models.user_info, "user_id");
    },
    user_type: function() {
      return this.hasOne(Models.user_type, "user_id");
    }
  }),
  user_info: bookshelf.Model.extend({
    tableName: "baas2_dashboard.user_info",
    hasTimestamps: true,
    softDelete: true,
    avater: function() {
      return this.belongsTo(Models.user_image, "avater_id");
    }
  }),
  charges: bookshelf.Model.extend({
    tableName: "baas2_dashboard.charges",
    hasTimestamps: true
  }),
  privilege: bookshelf.Model.extend({
    tableName: "baas2_dashboard.privilege",
    hasTimestamps: true,
    softDelete: true
  }),
  baas_privilege: bookshelf.Model.extend({
    tableName: "baas2_dashboard.baas_privilege",
    hasTimestamps: true,
    softDelete: true
  }),
  user_type: bookshelf.Model.extend({
    tableName: "baas2_dashboard.user_type",
    hasTimestamps: true,
    softDelete: true
  }),
  // 验证码
  verify: bookshelf.Model.extend({
    tableName: "baas2_dashboard.verify",
    hasTimestamps: true
  }),
  user_image: bookshelf.Model.extend({
    tableName: "baas2_dashboard.user_image",
    hasTimestamps: true
  }),
  email: bookshelf.Model.extend({
    tableName: "baas2_dashboard.email",
    hasTimestamps: true,
    softDelete: true
  }),
  invite_user: bookshelf.Model.extend({
    tableName: "baas2_dashboard.invite_user",
    hasTimestamps: true,
    user: function() {
      return this.belongsTo(Models.user_info, "invited_id", "user_id");
    }
  }),
  reward: bookshelf.Model.extend({
    tableName: "baas2_dashboard.reward",
    hasTimestamps: true,
    softDelete: true
  }),
  coupon: bookshelf.Model.extend({
    tableName: "baas2_dashboard.coupon",
    hasTimestamps: true,
    softDelete: true
  }),
  user_coupon: bookshelf.Model.extend({
    tableName: "baas2_dashboard.user_coupon",
    hasTimestamps: true,
    softDelete: true,
    coupon: function() {
      return this.belongsTo(Models.coupon, "coupon_id");
    }
  }),
  company: bookshelf.Model.extend({
    tableName: "baas2_dashboard.company",
    hasTimestamps: true,
    softDelete: true,
    image: function() {
      return this.belongsTo(Models.user_image, "license_id");
    }
  }),
  cost_log: bookshelf.Model.extend({
    tableName: "baas2_analysis.cost_log",
    hasTimestamps: true,
    user: function() {
      return this.belongsTo(Models.user, "user_id");
    }
  }),
  user_baas: bookshelf.Model.extend({
    tableName: "baas2_dashboard.user_baas",
    hasTimestamps: true,
    softDelete: true,
    baas: function() {
      return this.belongsTo(Models.baas, "baas_id");
    },
    charges: function() {
      return this.belongsTo(Models.charges, "charges_id");
    }
  }),
  plugins_poster: bookshelf.Model.extend({
    tableName: "baas2_dashboard.plugins_poster",
    hasTimestamps: true,
    softDelete: true,
    image: function() {
      return this.belongsTo(Models.file, "file_id");
    },
    plugins: function() {
      return this.belongsTo(Models.plugins, "plugins_id");
    }
  }),
  plugins: bookshelf.Model.extend({
    tableName: "baas2_dashboard.plugins",
    hasTimestamps: true,
    softDelete: true,
    image: function() {
      return this.belongsTo(Models.file, "file_id");
    }
  }),
  baas_plugins: bookshelf.Model.extend({
    tableName: "baas2_dashboard.baas_plugins",
    hasTimestamps: true,
    softDelete: true,
    plugins: function() {
      return this.belongsTo(Models.plugins, "addons_id");
    }
  }),
  user_notice: bookshelf.Model.extend({
    tableName: "baas2_dashboard.user_notice",
    hasTimestamps: true,
    softDelete: true,
    notice: function() {
      return this.belongsTo(Models.notice, "notice_id");
    }
  }),
  // 消息提醒
  notice: bookshelf.Model.extend({
    tableName: "baas2_dashboard.notice",
    hasTimestamps: true
  }),
  // 财务
  trade: bookshelf.Model.extend({
    tableName: "baas2_dashboard.trade",
    hasTimestamps: true
  }),
  // 收费列表
  recharge: bookshelf.Model.extend({
    tableName: "baas2_dashboard.recharge",
    hasTimestamps: true
  }),
  // 域名
  domain: bookshelf.Model.extend({
    tableName: "baas2_dashboard.domain",
    hasTimestamps: true,
    softDelete: true
  }),
  // 短信验证码
  sms: bookshelf.Model.extend({
    tableName: "baas2_plugin.sms",
    hasTimestamps: true,
    softDelete: true
  }),
  // 短信验证码
  sms_fee: bookshelf.Model.extend({
    tableName: "baas2_plugin.sms_fee",
    hasTimestamps: true,
    softDelete: true
  }),
  // 短信验证码
  plugins_smscode: bookshelf.Model.extend({
    tableName: "baas2_plugin.captcha_sms",
    hasTimestamps: true,
    softDelete: true
  }),
  // 图片验证码
  plugins_imgcode: bookshelf.Model.extend({
    tableName: "baas2_plugin.captcha_img",
    hasTimestamps: true,
    softDelete: true
  }),
  // 微信支付
  pay_weixin: bookshelf.Model.extend({
    tableName: "baas2_plugin.pay_weixin",
    hasTimestamps: true,
    softDelete: true,
    class: function() {
      return this.belongsTo(Models.class, "class_id");
    },
    function: function() {
      return this.belongsTo(Models.function, "function_id");
    }
  }),
  // 小程序支付
  pay_wxa: bookshelf.Model.extend({
    tableName: "baas2_plugin.pay_wxa",
    hasTimestamps: true,
    softDelete: true,
    class: function() {
      return this.belongsTo(Models.class, "class_id");
    },
    function: function() {
      return this.belongsTo(Models.function, "function_id");
    }
  }),
  // 支付宝支付
  pay_alipay: bookshelf.Model.extend({
    tableName: "baas2_plugin.pay_alipay",
    hasTimestamps: true,
    softDelete: true,
    class: function() {
      return this.belongsTo(Models.class, "class_id");
    },
    function: function() {
      return this.belongsTo(Models.function, "function_id");
    }
  }),
  // 邮件插件
  plugins_mail: bookshelf.Model.extend({
    tableName: "baas2_plugin.mail",
    hasTimestamps: true,
    softDelete: true
  }),

  request: bookshelf.Model.extend({
    tableName: "baas2_log.request",
    hasTimestamps: true,
    softDelete: true
  }),
  debug: bookshelf.Model.extend({
    tableName: "baas2_log.debug",
    hasTimestamps: true,
    softDelete: true
  }),
  request: bookshelf.Model.extend({
    tableName: "baas2_log.request",
    hasTimestamps: true
  }),
  baas_debug: bookshelf.Model.extend({
    tableName: "baas2_log.debug",
    hasTimestamps: true,
    softDelete: true,
    user: function() {
      return this.belongsTo(Models.user, "user_id");
    }
  }),
  // 短信记录
  sms_log: bookshelf.Model.extend({
    tableName: "baas2_log.sms",
    hasTimestamps: true,
    softDelete: true
  }),
  // 统计表
  statistics: bookshelf.Model.extend({
    tableName: "baas2_analysis.statistics",
    hasTimestamps: true
  })
};

const Mysql = {
  /** Shortcut for sql quote(string)
   * @param string
   * @return string
   */
  async q(string) {
    const data = await this.bookshelf.knex.raw(`SELECT QUOTE('${string}')`);
    return data[0][0][`QUOTE('${string}')`];
  },
  /** Escape database identifier
   * @param string
   * @return string
   */
  idf_escape(idf) {
    try {
      return "`" + idf.replace(".", "`.`") + "`";
    } catch (err) {
      return "`" + idf + "`";
    }
  },
  /** Get escaped table name
   * @param string
   * @return string
   */
  async table(database) {
    const sql = `show table status from ${"`" + database + "`"}`;

    const result = await this.bookshelf.knex.raw(sql);
    return result[0];
  },
  /** Get server version
   * @return string
   */
  async server_info(info) {
    return (await this.bookshelf.knex.raw(
      `show variables like '${info}'`
    ))[0][0].Value;
  },
  async queries(query) {
    try {
      await this.bookshelf.knex.raw(query);
      return true;
    } catch (err) {
      console.log(err);
      return false;
    }
  },
  /** Create database
   * @param db string 数据库名
   * @param collation string utf8_general_ci
   * @return string
   */
  async create_database(db, collation) {
    const sql =
      "CREATE DATABASE " +
      this.idf_escape(db) +
      (collation ? " COLLATE " + (await this.q(collation)) : "");

    try {
      const result = await this.bookshelf.knex.raw(sql);
      return {
        data: result[0],
        msg: "创建成功",
        code: 1
      };
    } catch (err) {
      return {
        data: err,
        msg: "创建失败",
        code: 0
      };
    }
  },
  /** Drop databases
   * @param array
   * @return bool
   */
  // async drop_database(database) {
  //     const sql = "DROP DATABASE " + this.idf_escape(database);
  //     try {
  //         const result = await this.bookshelf.knex.raw(sql);
  //         return {
  //             data: result[0],
  //             msg: "删除成功",
  //             code: 1
  //         };
  //     } catch (err) {
  //         return {
  //             data: err,
  //             msg: `删除失败`,
  //             code: 0
  //         };
  //     }
  // },
  /** Rename database from DB
   * @param string oldname
   * @param string newname
   * @param string
   * @return bool
   */
  async rename_database(oldname, newname, collation) {
    let result = false;
    const create_database = await this.create_database(newname, collation);
    if (create_database.code) {
      let rename = new Array();
      const tables = await this.table(oldname);

      for (let row of tables) {
        rename.push(
          this.idf_escape(oldname) +
            "." +
            this.idf_escape(row.Name) +
            " TO " +
            this.idf_escape(newname) +
            "." +
            this.idf_escape(row.Name)
        );
      }

      result =
        !rename.length ||
        (await this.queries("RENAME TABLE " + rename.join(", ")));
      if (result) {
        await this.queries("DROP DATABASE " + this.idf_escape(oldname));
      }
    }
    return result;
  },
  async fields(database, table_name, column_name) {
    let sql = "show full fields from `" + database + "`.`" + table_name + "`";
    if (column_name) {
      sql =
        "show full fields from `" +
        database +
        "`.`" +
        table_name +
        "` where field = '" +
        column_name +
        "'";
    }

    let fields = (await this.bookshelf.knex.raw(sql))[0];
    for (let key in fields) {
      let match = fields[key].Type.match(
        "^([^( ]+)(?:\\((.+)\\))?( unsigned)?( zerofill)?$"
      );
      fields[key].Type_index = match[1] ? match[1] : "";
      fields[key].Type_length = match[2] ? match[2] : "";
    }

    return column_name ? fields[0] : fields;
  },
  /** Get sorted grouped list of collates
   * @return array 排序规则
   */
  async collates() {
    let data = {};
    const collation = (await this.bookshelf.knex.raw("SHOW COLLATION"))[0];
    for (let row of collation) {
      data[row["Charset"]] = data[row["Charset"]] ? data[row["Charset"]] : [];
      data[row["Charset"]].push(row["Collation"]);
    }
    let collates = [];
    for (let key in data) {
      data[key].sort();
      collates.push({
        name: key,
        sub: data[key]
      });
    }
    collates = _.sortBy(collates, "name");
    return collates;
  },
  // 引擎列表
  async engines() {
    let engines = [];
    const data = (await this.bookshelf.knex.raw("SHOW ENGINES"))[0];
    for (let row of data) {
      if (row["Support"] != "NO") {
        engines.push(row["Engine"]);
      }
    }
    return engines;
  },
  // 类型列表
  types() {
    return [
      {
        name: "数字",
        sub: [
          "tinyint",
          "smallint",
          "mediumint",
          "int",
          "bigint",
          "decimal",
          "float",
          "double"
        ]
      },
      {
        name: "日期时间",
        sub: ["date", "datetime", "timestamp", "time", "year"]
      },
      {
        name: "字符串",
        sub: ["char", "varchar", "tinytext", "text", "mediumtext", "longtext"]
      },
      {
        name: "列表",
        sub: ["enum", "set"]
      },
      {
        name: "二进制",
        sub: [
          "bit",
          "binary",
          "varbinary",
          "tinyblob",
          "blob",
          "mediumblob",
          "longblob"
        ]
      },
      {
        name: "几何图形",
        sub: [
          "geometry",
          "point",
          "linestring",
          "polygon",
          "multipoint",
          "multilinestring",
          "multipolygon",
          "geometrycollection"
        ]
      }
    ];
  },
  // 函数
  functions() {
    return [
      "char_length",
      "date",
      "from_unixtime",
      "lower",
      "round",
      "sec_to_time",
      "time_to_sec",
      "upper"
    ];
  },
  // 集合
  grouping() {
    return [
      "avg",
      "count",
      "count distinct",
      "group_concat",
      "max",
      "min",
      "sum"
    ];
  },
  // 搜索
  operators() {
    return [
      "=",
      "<",
      ">",
      "<=",
      ">=",
      "!=",
      "LIKE",
      "LIKE %%",
      "REGEXP",
      "IN",
      "IS NULL",
      "NOT LIKE",
      "NOT REGEXP",
      "NOT IN",
      "IS NOT NULL",
      "SQL"
    ];
  },
  // mysql函数
  fus() {
    return [
      {
        name: "数学函数",
        sub: [
          {
            fn_name: "ABS(x)",
            fn_value: "ABS",
            describe: "返回x的绝对值",
            sql: "SELECT ABS(-1) -- 返回1"
          },
          {
            fn_name: "CEIL(x)",
            fn_value: "CEIL",
            describe: "返回大于或等于x的最小整数",
            sql: "SELECT CEIL(1.5) -- 返回2"
          },
          {
            fn_name: "FLOOR(x)",
            fn_value: "FLOOR",
            describe: "返回小于或等于x的最大整数",
            sql: "SELECT FLOOR(1.5) -- 返回1"
          },
          {
            fn_name: "RAND(x)",
            fn_value: "RAND",
            describe: "返回0->1的随机数，x值相同时返回的随机数相同",
            sql: "SELECT RAND(2) --1.5865798029924"
          },
          {
            fn_name: "SIGN(x)",
            fn_value: "SIGN",
            describe: "返回x的符号，x是负数、0、正数分别返回-1、0和1",
            sql: "SELECT SIGN(-10) -- (-1)"
          },
          {
            fn_name: "PI()",
            fn_value: "PI",
            describe: "返回圆周率(3.141593)",
            sql: "SELECT PI() --3.141593"
          },
          {
            fn_name: "TRUNCATE(x,y)",
            fn_value: "TRUNCATE",
            describe:
              "返回数值x保留到小数点后y位的值（与ROUND最大的区别是不会进行四舍五入）",
            sql: "SELECT TRUNCATE(1.23456,3) -- 1.234"
          },
          {
            fn_name: "ROUND(x)",
            fn_value: "ROUND",
            describe: "返回离x最近的整数",
            sql: "SELECT ROUND(1.23456) --1"
          },
          {
            fn_name: "ROUND(x,y)",
            fn_value: "ROUND",
            describe: "保留x小数点后y位的值，但截断时要进行四舍五入",
            sql: "SELECT ROUND(1.23456,3) -- 1.235"
          },
          {
            fn_name: "POW(x,y)",
            fn_value: "POW",
            describe: "返回x的y次方",
            sql: "SELECT POW(2,3) -- 8"
          },
          {
            fn_name: "SQRT(x)",
            fn_value: "SQRT",
            describe: "返回x的平方根",
            sql: "SELECT SQRT(25) -- 5"
          },
          {
            fn_name: "EXP(x)",
            fn_value: "EXP",
            describe: "返回e的x次方",
            sql: "SELECT EXP(3) -- 20.085536923188"
          },
          {
            fn_name: "MOD(x,y)",
            fn_value: "MOD",
            describe: "返回x除以y以后的余数",
            sql: "SELECT MOD(5,2) -- 1"
          },
          {
            fn_name: "LOG(x)",
            fn_value: "LOG",
            describe: "返回自然对数(以e为底的对数)",
            sql: "SELECT LOG(20.085536923188) -- 3"
          },
          {
            fn_name: "LOG10(x)",
            fn_value: "LOG10",
            describe: "返回以10为底的对数",
            sql: "SELECT LOG10(100) -- 2"
          },
          {
            fn_name: "RADIANS(x)",
            fn_value: "RADIANS",
            describe: "将角度转换为弧度",
            sql: "SELECT RADIANS(180) -- 3.1415926535898"
          },
          {
            fn_name: "DEGREES(x)",
            fn_value: "DEGREES",
            describe: "将弧度转换为角度",
            sql: "SELECT DEGREES(3.1415926535898) -- 180"
          },
          {
            fn_name: "SIN(x)",
            fn_value: "SIN",
            describe: "求正弦值(参数是弧度)",
            sql: "SELECT SIN(RADIANS(30)) -- 0.5"
          },
          {
            fn_name: "ASIN(x)",
            fn_value: "ASIN",
            describe: "求反正弦值(参数是弧度)",
            sql: ""
          },
          {
            fn_name: "COS(x)",
            fn_value: "COS",
            describe: "求余弦值(参数是弧度)",
            sql: ""
          },
          {
            fn_name: "ACOS(x)",
            fn_value: "ACOS",
            describe: "求反余弦值(参数是弧度)",
            sql: ""
          },
          {
            fn_name: "TAN(x)",
            fn_value: "TAN",
            describe: "求正切值(参数是弧度)",
            sql: ""
          },
          {
            fn_name: "ATAN(x)",
            fn_value: "ATAN",
            describe: "求反正切值(参数是弧度)",
            sql: ""
          },
          {
            fn_name: "COT(x)",
            fn_value: "COT",
            describe: "求余切值(参数是弧度)",
            sql: ""
          }
        ]
      },
      {
        name: "字符串函数",
        sub: [
          {
            fn_name: "CHAR_LENGTH(s)",
            fn_value: "CHAR_LENGTH",
            describe: "返回字符串s的字符数",
            sql: `SELECT CHAR_LENGTH('你好123') -- 5`
          },
          {
            fn_name: "LENGTH(s)",
            fn_value: "LENGTH",
            describe: "返回字符串s的长度",
            sql: `SELECT LENGTH('你好123') -- 9`
          },
          {
            fn_name: "CONCAT(s1,s2,...)",
            fn_value: "CONCAT",
            describe: "将字符串s1,s2等多个字符串合并为一个字符串",
            sql: `SELECT CONCAT('12','34') -- 1234`
          }
        ]
      },
      {
        name: "日期时间函数",
        sub: [
          {
            fn_name: "CURDATE()",
            fn_value: "CURDATE",
            describe: "返回当前日期",
            sql: `SELECT CURDATE() ->2014-12-17`
          },
          // {
          //     fn_name: "CURRENT_DATE()",
          //     fn_value: "CURRENT_DATE",
          //     describe: "返回当前日期",
          //     sql: `SELECT CURRENT_DATE() ->2014-12-17`
          // },
          {
            fn_name: "CURTIME()",
            fn_value: "CURTIME",
            describe: "返回当前时间",
            sql: `SELECT CURTIME() ->15:59:02`
          },
          // {
          //     fn_name: "CURRENT_TIME",
          //     fn_value: "CURRENT_TIME",
          //     describe: "返回当前时间",
          //     sql: `SELECT CURRENT_TIME ->15:59:02`
          // },
          {
            fn_name: "NOW()",
            fn_value: "NOW",
            describe: "返回当前日期和时间",
            sql: `SELECT NOW() ->2014-12-17 15:59:02`
          },
          {
            fn_name: "UNIX_TIMESTAMP()",
            fn_value: "UNIX_TIMESTAMP",
            describe: "以UNIX时间戳的形式返回当前时间",
            sql: `SELECT UNIX_TIMESTAMP() ->1418803177`
          }
        ]
      },
      {
        name: "加密函数",
        sub: [
          {
            fn_name: "PASSWORD(str)",
            fn_value: "PASSWORD",
            describe:
              "该函数可以对字符串str进行加密，一般情况下，PASSWORD(str)用于给用户的密码加密",
            sql: `SELECT PASSWORD('123')
    ->*23AE809DDACAF96AF0FD78ED04B6A265E05AA257`
          },
          {
            fn_name: "MD5(str)",
            fn_value: "MD5",
            describe:
              "MD5(str)函数可以对字符串str进行散列，可以用于一些普通的不需要解密的数据加密",
            sql: `SELECT md5('123')
    ->202cb962ac59075b964b07152d234b70`
          },
          {
            fn_name: "ENCODE(str,pswd_str)",
            fn_value: "ENCODE",
            describe:
              "ENCODE函数可以使用加密密码pswd_str来加密字符串str，加密结果是二进制数，需要使用BLOB类型的字段保存。该函数与DECODE是一对，需要同样的密码才能够解密",
            sql: `SELECT ENCODE('123','xxoo')
    ->;vx`
          },
          {
            fn_name: "DECODE(crypt_str,pswd_str)",
            fn_value: "DECODE",
            describe: "该函数与ENCODE是一对，解密",
            sql: `SELECT DECODE(';vx','xxoo')
    ->123`
          }
        ]
      },
      {
        name: "其他函数",
        sub: [
          {
            fn_name: "FORMAT(x,n)",
            fn_value: "FORMAT",
            describe:
              "FORMAT(x,n)函数可以将数字x进行格式化，将x保留到小数点后n位。",
            sql: `SELECT FORMAT(3.1415926,3)
    ->3.142`
          },
          {
            fn_name: "ASCII(s)",
            fn_value: "ASCII",
            describe: "返回字符串s的第一个字符的ASCII码",
            sql: ``
          },
          {
            fn_name: "BIN(x)",
            fn_value: "BIN",
            describe: "返回x的二进制编码",
            sql: ``
          }
        ]
      }
    ];
  }
};

module.exports = {
  getBookshelf,
  bookshelf,
  Models,
  Mysql
};
